package com.ficus.road.maintain.service;

import com.ficus.road.maintain.core.model.coverage.CycleNum;
import com.ficus.road.maintain.dao.coverage.CycleNumDao;
import com.ficus.road.maintain.third.zh.coverage.ZHCycleNum;
import com.ficus.road.maintain.util.MyDateUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiawen yang
 * 2022/3/17 下午2:47
 */
@Service
public class CycleNumService {

    @Autowired
    CycleNumDao cycleNumDao;
    @Autowired
    ZHCycleNum zhCycleNum;

    public String getLastCycleNum(String currentCycleNum) {
        List<CycleNum> currentList = cycleNumDao.findByQuery(new Query(Criteria.where("cycle_num").is(currentCycleNum)));
        if (CollectionUtils.isEmpty(currentList)) {
            return null;
        }
        String dateStr = currentList.get(0).getId();
        Date date = MyDateUtil.strParseDate(dateStr, "yyyy-MM-dd");
        Date lastDate = DateUtils.addDays(date, -3);
        String lastDateStr = MyDateUtil.dateFormatStr(lastDate, "yyyy-MM-dd");
        CycleNum fetch = cycleNumDao.fetch(lastDateStr);
        if (ObjectUtils.isEmpty(fetch)) {
            return null;
        }
        return fetch.getCycleNum();
    }

    public List<String> getLast2CycleNum() {
        Query cycle_num = new Query().with(Sort.by(Sort.Order.desc("cycle_num"))).limit(4);
        List<CycleNum> currentList = cycleNumDao.findByQuery(cycle_num);
        if (CollectionUtils.isEmpty(currentList)) {
            return null;
        }

        return currentList.stream().map(CycleNum::getCycleNum)
                .collect(Collectors.toSet()).stream().limit(2)
                .sorted(Comparator.comparing(Object::toString).reversed())
                .collect(Collectors.toList());
    }

    public String getCurrentCycleNum() {
        CycleNum fetch = cycleNumDao.fetch(MyDateUtil.dateFormatStr(new Date(), "yyyy-MM-dd"));
        if (ObjectUtils.isEmpty(fetch)) {
            return getLatestCycleNum();
        }
        return fetch.getCycleNum();
    }

    private String getLatestCycleNum() {
        CycleNum cycleNum = cycleNumDao.findOne(new Query().with(new Sort(Sort.Direction.DESC, "_id")));
        return cycleNum.getCycleNum();
    }

    public String getMonthAgoCycleNum() {
        Date monthAgo = DateUtils.addDays(new Date(), -30);
        String monthAgoStr = MyDateUtil.dateFormatStr(monthAgo, "yyyy-MM-dd");
        CycleNum fetch = cycleNumDao.fetch(monthAgoStr);
        if (ObjectUtils.isEmpty(fetch)) {
            return cycleNumDao.findAll().stream().sorted(Comparator.comparing(item -> item.getId())).findFirst().get().getCycleNum();
        }
        return fetch.getCycleNum();
    }

    public List<String> getMonthAgoCycleNumList() {
        Date monthAgo = DateUtils.addDays(new Date(), -30);
        String monthAgoStr = MyDateUtil.dateFormatStr(monthAgo, "yyyy-MM-dd");
        Query query = new Query(Criteria.where("_id").gte(monthAgoStr));
        query.with(new Sort(Sort.Direction.DESC, "_id"));
        List<CycleNum> cycleNumList = cycleNumDao.findByQuery(query);
        return cycleNumList.stream().map(CycleNum::getCycleNum).distinct().collect(Collectors.toList());
    }

    public List<CycleNum> getDateByCycleNum(String cycleNum) {
        Query query = new Query(Criteria.where("cycle_num").is(cycleNum));
        query.with(new Sort(Sort.Direction.ASC, "_id"));
        List<CycleNum> res = cycleNumDao.findByQuery(query);
        return res;
    }

    public CycleNum getByDate(String date) {
        Query query = new Query(Criteria.where("_id").is(date));
        return cycleNumDao.findOne(query);
    }

    /**
     * 判断是否是周期的第一天
     *
     * @return
     */
    public Boolean judgeFirstDateOfCycleNum() {
        String dateStr = MyDateUtil.dateFormatStr(new Date(), "yyyy-MM-dd");
        String currentCycleNum = getCurrentCycleNum();
        List<CycleNum> dateByCycleNum = getDateByCycleNum(currentCycleNum);
        if (dateByCycleNum.size() == 1) {
            return Boolean.TRUE;
        } else if (dateByCycleNum.size() == 0) {
            zhCycleNum.refreshCycleNum();
            return judgeFirstDateOfCycleNum();
        } else {
            return Boolean.FALSE;
        }
    }

    /**
     * 判断给定的时间戳是否属于当前周期
     *
     * @return
     */
    public Boolean judgeTimestampIsCycleNum(long timestamp) {
        List<String> cycleNumList = getDateByCycleNum(getCurrentCycleNum()).stream().map(CycleNum::getId).collect(Collectors.toList());
        String firstDateStr = cycleNumList.get(0);
        String lastDateStr = cycleNumList.get(cycleNumList.size() - 1);
        Date startOfCycleNum = MyDateUtil.getStartOfDay(MyDateUtil.strParseDate(firstDateStr, "yyyy-MM-dd"));
        Date endOfCycleNum = MyDateUtil.getEndOfDay(MyDateUtil.strParseDate(lastDateStr, "yyyy-MM-dd"));
        Date date = new Date(timestamp);
        if (date.compareTo(startOfCycleNum) > 0 && date.compareTo(endOfCycleNum) < 0) {
            return true;
        }
        return false;
    }
}
